// Copyright 2012 Square, Inc.
package com.squareup.timessquare;

import com.example.library.ResourceTable;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.agp.text.Font;
import ohos.app.Context;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

/**
 * MonthView
 */
public class MonthView extends DependentLayout {
    private Text title;
    private CalendarGridView grid;
    private Component dayNamesHeaderRowView;
    private Listener listener;
    private List<CalendarCellDecorator> decorators;
    private boolean isRtl;
    private Locale locale;
    private boolean alwaysDigitNumbers;

    /**
     * create
     *
     * @param parent                       parent
     * @param inflater                     inflater
     * @param weekdayNameFormat            weekdayNameFormat
     * @param listener                     listener
     * @param today                        today
     * @param dividerColor                 dividerColor
     * @param dayBackgroundResId           dayBackgroundResId
     * @param dayTextColorResId            dayTextColorResId
     * @param titleTextStyle               titleTextStyle
     * @param displayHeader                displayHeader
     * @param headerTextColor              headerTextColor
     * @param showAlwaysDigitNumbers       showAlwaysDigitNumbers
     * @param locale                       locale
     * @param adapter                      adapter
     * @param showDayNamesHeaderRowView showDayNamesHeaderRowView
     * @return MonthView
     */
    public static MonthView create(
            ComponentContainer parent,
            LayoutScatter inflater,
            DateFormat weekdayNameFormat,
            Listener listener,
            Calendar today,
            int dividerColor,
            int dayBackgroundResId,
            int dayTextColorResId,
            int titleTextStyle,
            boolean displayHeader,
            int headerTextColor,
            boolean showDayNamesHeaderRowView,
            Locale locale,
            boolean showAlwaysDigitNumbers,
            DayViewAdapter adapter) {
        return create(
                parent,
                inflater,
                weekdayNameFormat,
                listener,
                today,
                dividerColor,
                dayBackgroundResId,
                dayTextColorResId,
                titleTextStyle,
                displayHeader,
                headerTextColor,
                showDayNamesHeaderRowView,
                showAlwaysDigitNumbers,
                null,
                locale,
                adapter);
    }

    /**
     * create
     *
     * @param parent                       parent
     * @param inflater                     inflater
     * @param weekdayNameFormat            weekdayNameFormat
     * @param listener                     listener
     * @param today                        today
     * @param dividerColor                 dividerColor
     * @param dayBackgroundResId           dayBackgroundResId
     * @param dayTextColorResId            dayTextColorResId
     * @param titleTextStyle               titleTextStyle
     * @param displayHeader                displayHeader
     * @param headerTextColor              headerTextColor
     * @param displayDayNamesHeaderRowView displayDayNamesHeaderRowView
     * @param showAlwaysDigitNumbers       showAlwaysDigitNumbers
     * @param decorators                   decorators
     * @param locale                       locale
     * @param adapter                      adapter
     * @return MonthView
     */
    public static MonthView create(
            ComponentContainer parent,
            LayoutScatter inflater,
            DateFormat weekdayNameFormat,
            Listener listener,
            Calendar today,
            int dividerColor,
            int dayBackgroundResId,
            int dayTextColorResId,
            int titleTextStyle,
            boolean displayHeader,
            int headerTextColor,
            boolean displayDayNamesHeaderRowView,
            boolean showAlwaysDigitNumbers,
            List<CalendarCellDecorator> decorators,
            Locale locale,
            DayViewAdapter adapter) {
        final MonthView view = (MonthView) inflater.parse(ResourceTable.Layout_month_view, parent, false);

        // Set the views
        view.title = new Text(parent.getContext());
        view.grid = (CalendarGridView) view.findComponentById(ResourceTable.Id_calendar_grid);
        view.dayNamesHeaderRowView = view.findComponentById(ResourceTable.Id_day_names_header_row);

        // Add the month title as the first child of MonthView
        view.addComponent(view.title, 0);

        view.setDayViewAdapter(adapter);
        view.setDividerColor(dividerColor);
        view.setDayTextColor(dayTextColorResId);
        view.setDisplayHeader(displayHeader);
        view.setHeaderTextColor(headerTextColor);

        if (dayBackgroundResId != 0) {
            view.setDayBackground(dayBackgroundResId);
        }

        view.isRtl = isRtl(locale);
        view.locale = locale;
        view.alwaysDigitNumbers = showAlwaysDigitNumbers;
        int firstDayOfWeek = today.getFirstDayOfWeek();
        final CalendarRowView headerRow = (CalendarRowView) view.grid.getComponentAt(0);

        if (displayDayNamesHeaderRowView) {
            final int originalDayOfWeek = today.get(Calendar.DAY_OF_WEEK);
            for (int offset = 0; offset < 7; offset++) {
                today.set(Calendar.DAY_OF_WEEK, getDayOfWeek(firstDayOfWeek, offset, view.isRtl));
                final Text textView = (Text) headerRow.getComponentAt(offset);
                textView.setText(weekdayNameFormat.format(today.getTime()));
            }
            today.set(Calendar.DAY_OF_WEEK, originalDayOfWeek);
        } else {
            view.dayNamesHeaderRowView.setVisibility(Component.HIDE);
        }

        view.listener = listener;
        view.decorators = decorators;
        return view;
    }

    private static int getDayOfWeek(int firstDayOfWeek, int offset, boolean isRtl) {
        int dayOfWeek = firstDayOfWeek + offset;
        if (isRtl) {
            return 8 - dayOfWeek;
        }
        return dayOfWeek;
    }

    private static boolean isRtl(Locale locale) {
        // TODO convert the build to gradle and use getLayoutDirection instead of this (on 17+)?
        final int directionality = Character.getDirectionality(locale.getDisplayName(locale).charAt(0));
        return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT
                || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
    }

    public MonthView(Context context, AttrSet attrs) {
        super(context, attrs);
    }

    /**
     * setDecorators
     *
     * @param decorators decorators
     */
    public void setDecorators(List<CalendarCellDecorator> decorators) {
        this.decorators = decorators;
    }

    public List<CalendarCellDecorator> getDecorators() {
        return decorators;
    }

    /**
     * 初始化
     *
     * @param month         月
     * @param cells         cells
     * @param displayOnly   displayOnly
     * @param titleTypeface titleTypeface
     * @param dateTypeface  dateTypeface
     */
    public void init(MonthDescriptor month, List<List<MonthCellDescriptor>> cells, boolean displayOnly, Font titleTypeface, Font dateTypeface) {
        long start = System.currentTimeMillis();
        title.setText(month.getLabel());
        NumberFormat numberFormatter;
        if (alwaysDigitNumbers) {
            numberFormatter = NumberFormat.getInstance(Locale.US);
        } else {
            numberFormatter = NumberFormat.getInstance(locale);
        }
        final int numRows = cells.size();
        grid.setNumRows(numRows);
        for (int i = 0; i < 6; i++) {
            CalendarRowView weekRow = (CalendarRowView) grid.getComponentAt(i + 1);
            weekRow.setListener(listener);
            if (i < numRows) {
                weekRow.setVisibility(VISIBLE);
                List<MonthCellDescriptor> week = cells.get(i);
                for (int c = 0; c < week.size(); c++) {
                    MonthCellDescriptor cell = week.get(isRtl ? 6 - c : c);
                    CalendarCellView cellView = (CalendarCellView) weekRow.getComponentAt(c);
                    String cellDate = numberFormatter.format(cell.getValue());
                    if (!cellView.getDayOfMonthTextView().getText().equals(cellDate)) {
                        cellView.getDayOfMonthTextView().setText(cellDate);
                    }
                    cellView.setEnabled(cell.isCurrentMonth());
                    cellView.setClickable(!displayOnly);
                    cellView.setSelectable(cell.isSelectable());
                    cellView.setSelected(cell.isSelected());
                    cellView.setCurrentMonth(cell.isCurrentMonth());
                    cellView.setToday(cell.isToday());
                    cellView.setRangeState(cell.getRangeState());
                    cellView.setHighlighted(cell.isHighlighted());
                    cellView.setTag(cell);
                    if (null != decorators) {
                        for (CalendarCellDecorator decorator : decorators) {
                            decorator.decorate(cellView, cell.getDate());
                        }
                    }
                }
            } else {
                weekRow.setVisibility(Component.HIDE);
            }
        }
        if (titleTypeface != null) {
            title.setFont(titleTypeface);
        }
    }

    /**
     * setDividerColor
     *
     * @param color color
     */
    public void setDividerColor(int color) {
        grid.setDividerColor(color);
    }

    /**
     * setDayBackground
     *
     * @param resId resId
     */
    public void setDayBackground(int resId) {
        grid.setDayBackground(resId);
    }

    /**
     * setDayTextColor
     *
     * @param resId resId
     */
    public void setDayTextColor(int resId) {
        grid.setDayTextColor(resId);
    }

    /**
     * setDayViewAdapter
     *
     * @param adapter adapter
     */
    public void setDayViewAdapter(DayViewAdapter adapter) {
        grid.setDayViewAdapter(adapter);
    }

    /**
     * setDisplayHeader
     *
     * @param displayHeader displayHeader
     */
    public void setDisplayHeader(boolean displayHeader) {
        grid.setDisplayHeader(displayHeader);
    }

    /**
     * setHeaderTextColor
     *
     * @param color color
     */
    public void setHeaderTextColor(int color) {
        grid.setHeaderTextColor(color);
    }

    /**
     * Listener
     */
    public interface Listener {
        /**
         * handleClick
         *
         * @param cell cell
         */
        void handleClick(MonthCellDescriptor cell);
    }
}
